/**
 * @author Ahammer
 * @date    2009 05
 * @update  2010 11 new Color_Deconvolution version with new colors (H&E2, Masson Trichrome,..)
 * @update  2010 11 DAB, DAB NBTBCIP, colors 
 */

/*
 * This is an implementation of an ImageJ plugin by G.Landini
 * http://www.dentistry.bham.ac.uk/landinig/software/cdeconv/cdeconv.html
 * 
 */

/*
 * This file is part of Iqm.
 * Copyright (c) 2010-2011 Helmut Ahammer
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package op;

import ij.ImagePlus;
import ijplugin.IqmColour_Deconvolution;
import java.awt.Image;
import java.awt.image.IndexColorModel;
import java.awt.image.renderable.ParameterBlock;
import javax.media.jai.JAI;
import javax.media.jai.LookupTableJAI;
import javax.media.jai.ParameterBlockJAI;
import javax.media.jai.PlanarImage;
import main.Board;

/**
 * This is the main image processing class
 * There exist two approaches:
 * A user defined JAI operator is just called 
 * or:
 * The actual processing is implemented in this class 
 */
public class IqmColDeconOperator{ 


  public IqmColDeconOperator() {
	  //WARNING: Don't declare fields here
	  //Fields declared here aren't thread safe!   
  }
  /**
   * 
   * @param ParametrBlockJAI pb
   */
  public Object run(ParameterBlockJAI pb){
		Object ob = null;
		//ob = JAI.create("IqmcolDecon".toLowerCase(), pb, null);   
		int colDecon    = pb.getIntParameter("ColDecon"); 
		PlanarImage pi  = (PlanarImage) pb.getRenderedSource(0);
	  	Image image     = pi.getAsBufferedImage();
	  	String imgName  = (String) pi.getProperty("image_name");
	  	String fileName = (String) pi.getProperty("file_name");
	  	
	 	//int sampleModel = pi.getSampleModel().getDataType();
		//new ImagePlus("", pi.getAsBufferedImage()).show();
		//ImagePlus imp = IJ.getImage();
		ImagePlus imp = new ImagePlus("", image);
	
		//this part uses ImageJ's Color Deconvolution
		String vectors = null;
	  	if (colDecon == 0)  vectors="H&E";
	  	if (colDecon == 1)  vectors="H&E 2";
	  	if (colDecon == 2)  vectors="H DAB";
	  	if (colDecon == 3)  vectors="Feulgen Light Green";
	  	if (colDecon == 4)  vectors="Giemsa";
	  	if (colDecon == 5)  vectors="FastRed FastBlue DAB";
	  	if (colDecon == 6)  vectors="Methyl Green DAB";
	  	if (colDecon == 7)  vectors="H&E DAB";
	  	if (colDecon == 8)  vectors="H AEC";
	  	if (colDecon == 9)  vectors="Azan-Mallory";
	  	if (colDecon == 10) vectors="Masson Trichrome";
	  	if (colDecon == 11) vectors="Alcian blue & H";
	  	if (colDecon == 12) vectors="H PAS";
	  	if (colDecon == 13) vectors="DAB NBTBCIP";  //only in Iqm version
	  	if (colDecon == 14) vectors="DAB";          //only in Iqm version
	  	if (colDecon == 15) vectors="RGB";
	  	if (colDecon == 16) vectors="CMY";
	  	if (colDecon == 17) vectors="User values";
	  	ImagePlus[] resultStack;
	  	IqmColour_Deconvolution ijPlugIn = new IqmColour_Deconvolution();  //Palette images
	  	resultStack = ijPlugIn.run(imp, vectors);
	  	
	  	if (resultStack == null){
	  		Board.appendTexln("IqmColDeconOperator: Convolution result is null");
	  		return pi;
	  	}
		Image image1 = resultStack[0].getImage();//.getBufferedImage();
		Image image2 = resultStack[1].getImage();//.getBufferedImage();
		Image image3 = resultStack[2].getImage();//.getBufferedImage();
			
		PlanarImage pi1 = JAI.create("AWTImage", image1);	
		PlanarImage pi2 = JAI.create("AWTImage", image2);	
		PlanarImage pi3 = JAI.create("AWTImage", image3);	

		//System.out.println("pi1. colormodel: " + pi1.getColorModel());
		
        IndexColorModel icm = (IndexColorModel)pi1.getColorModel();
        byte[][] data = new byte[3][icm.getMapSize()];
        icm.getReds(data[0]);
        icm.getGreens(data[1]);
        icm.getBlues(data[2]);
        LookupTableJAI lut = new LookupTableJAI(data);
        pi1 = JAI.create("lookup", pi1, lut);  //RGB image
        
        icm = (IndexColorModel)pi2.getColorModel();
        data = new byte[3][icm.getMapSize()];
        icm.getReds(data[0]);
        icm.getGreens(data[1]);
        icm.getBlues(data[2]);
        lut = new LookupTableJAI(data);
        pi2 = JAI.create("lookup", pi2, lut);  //RGB image
        
        icm = (IndexColorModel)pi3.getColorModel();
        data = new byte[3][icm.getMapSize()];
        icm.getReds(data[0]);
        icm.getGreens(data[1]);
        icm.getBlues(data[2]);
        lut = new LookupTableJAI(data);
        pi3 = JAI.create("lookup", pi3, lut);  //RGB image
        
		ParameterBlock pb2 = new ParameterBlock();        
		double[][] m = {{ 0.114, 0.587, 0.299, 0 }};

		pb2.addSource(pi1);
		pb2.add(m);
		pi1 = JAI.create("bandcombine", pb2, null);  //Gray

		pb2.removeSources();
	    pb2.removeParameters();
		pb2.addSource(pi2);
		pb2.add(m);
		pi2 = JAI.create("bandcombine", pb2, null);  //Gray
		
		pb2.removeSources();
	    pb2.removeParameters();
		pb2.addSource(pi3);
		pb2.add(m);
		pi3 = JAI.create("bandcombine", pb2, null);  //Gray
		
		//System.out.println("pi1. colormodel: " + pi1.getColorModel());


		
		//new ImagePlus("", pi1.getAsBufferedImage()).show();
		
		//ParameterBlock pb2 = new ParameterBlock();
//		ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), new int[] { 8, 8, 8 }, false, true, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
//		pb2.addSource(pi1);
//		pb2.add(cm);
//		pi1 = JAI.create("ColorConvert", pb2);
//		System.out.println("pi1. colormodel: " + pi1.getColorModel());
//		
//
//	   
//		pb2.removeSources();
//	    pb2.removeParameters();
//		pb2.addSource(pi2);
//		pb2.add(cm);
//		pi2 = JAI.create("ColorConvert", pb2);
//		
//	    pb2.removeSources();
//	    pb2.removeParameters();
//		pb2.addSource(pi3);
//		pb2.add(cm);
//		pi3 = JAI.create("ColorConvert", pb2);
		//RenderingHints rh = new RenderingHints(JAI.KEY_REPLACE_INDEX_COLOR_MODEL, null);

		
	    pb2.removeSources();
	    pb2.removeParameters();		
	    pb2.setSource(pi1,0);	
	    pb2.setSource(pi2,1);	
	    pb2.setSource(pi3,2);	
		ob = JAI.create("bandmerge", pb2);
		//System.out.println("ob. colormodel: " + ((PlanarImage)ob).getColorModel());
		
//		WritableRaster pixelraster = ((PlanarImage) ob).copyData();
//		ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] { 8, 8, 8 }, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
//		SampleModel sm= cm.createCompatibleSampleModel(pi.getWidth(), pi.getHeight());
//		ob = new TiledImage(0,0,pi.getWidth(), pi.getHeight(),0,0,sm,cm);
//		((TiledImage) ob).setData(pixelraster); 
		
		//new ImagePlus("", ((PlanarImage) ob).getAsBufferedImage()).show();
		
		
		
//		ImageLayout layout = new ImageLayout();
//		ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB), new int[] { 8, 8, 8 }, false, true, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
//		layout.setColorModel(cm);
//		RenderingHints hints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);
		
//	    pb2.removeSources();
//	    pb2.removeParameters();
//	    pb2.addSource(ob);
//		pb2.add(sampleModel);  	
//		ob = JAI.create("format",  pb2); //imp ist zb. bei RGB vom Typ int anstatt byte 

		imp.flush();	
		//wr.setDataElements(minX, minY, pi.getData()); //
		//wr = (WritableRaster) pi.getData();   gehr hier nicht, da AWT image Tile Info verliert!!!!!!
		((PlanarImage) ob).setProperty("image_name", imgName);
		((PlanarImage)ob).setProperty("file_name", fileName);	
		return ob;
  }
}
